
#include "win32window.h"
#include <cstdio>

namespace tinkle {

HINSTANCE Win32Window::_instance = GetModuleHandle(NULL);
LPTSTR g_wndClassName = TEXT("BaseWindowClass");
ATOM Win32Window::_wndClass = 0;

Win32Window::Win32Window()
    : _handle(NULL) {
    // blank line
}

Win32Window::~Win32Window() {
    // blank line
}

bool Win32Window::Create(HWND parent, LPCTSTR title, DWORD style,
                                           DWORD exStyle, int x, int y, int cx, int cy) {
    if (_handle) {
        // window already exists.
        return false;
    }
    if (!_wndClass) {
        // class not registered, register it.
        WNDCLASSEX wcex;
        memset(&wcex, 0, sizeof(wcex));
        wcex.cbSize = sizeof(wcex);
        wcex.hInstance = _instance;
        wcex.lpfnWndProc = &Win32Window::WndProc;
        wcex.lpszClassName = g_wndClassName;
        _wndClass = RegisterClassEx(&wcex);
        if (!_wndClass) {
            printf ("Register class failed\n");
            return false;
        }
    }
    _handle = CreateWindowEx(exStyle, g_wndClassName, title, style, x, y,
                                               cx, cy, parent, NULL, _instance, this);
    if (!_handle) {
        return false;
    }
    // save a class pointer into a window' s GWL_USERDATA field, so that we
    // can get a class pointer from a window handle.
    SetWindowLongPtr(_handle, GWL_USERDATA, (LONG)(LONG_PTR)this);
    return true;
}

HWND Win32Window::Handle() const {
    return _handle;
}

bool Win32Window::OnMessage(UINT msg, WPARAM wParam,
    LPARAM lParam, LRESULT &result) {
    switch (msg) {
    case WM_CLOSE:
        break;
    }
    return true;
}

LRESULT CALLBACK Win32Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                                        LPARAM lParam) {
    // get a Win32Window class pointer so that we can call Win32Window' s
    // member function.
    Win32Window *that = (Win32Window *)GetWindowLongPtr(hwnd, GWL_USERDATA);
    if (that) {
        LRESULT result = 0;
        bool isHandled = that->OnMessage(msg, wParam, lParam, result);
        if (isHandled) {
            return result;
        }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

}